#ifndef MyController_hpp
#define MyController_hpp

#include "../dto/RenameDTO.hpp"
#include "../activePage/downloadFile.h"
#include "../otherLib/base64.h"
#include "../otherLib/URLDecode.h"
#include "../otherLib/outputHex.cpp"
#include "../otherLib/BEtoLE.hpp"
#include <oatpp/web/server/api/ApiController.hpp>
#include <oatpp/core/macro/codegen.hpp>
#include <oatpp/core/macro/component.hpp>
#include <oatpp-websocket/oatpp-websocket/Handshaker.hpp>
#include <oatpp/network/ConnectionHandler.hpp>
#include <oatpp/core/data/stream/FileStream.hpp>
#include <string>
#include <sstream>
#include <fmt/format.h>
#include <fstream>
#include <iostream>

#include OATPP_CODEGEN_BEGIN(ApiController)

class MyController : public oatpp::web::server::api::ApiController
{
    private:
        OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, websocketConnectionHandler, "websocket");
    public:
        MyController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>,objectMapper))
        : oatpp::web::server::api::ApiController(objectMapper)
        {}

    public:
        ENDPOINT("GET","/fileBrowser",fileBrowser,QUERIES(QueryParams,queryParams))
        {
            downloadFilePage aPage;
            std::string currentPath={};
            if(queryParams.get("path")==nullptr)
                currentPath="/";
            else
                currentPath=queryParams.get("path");
            if(!aPage.response(currentPath))
                return createResponse(Status::CODE_500,"FileBrowser ERROR");
            std::wstring_convert<std::codecvt_utf8<wchar_t>> charConvert;
            std::wstring outputData=aPage.getOutputString().str();
            auto response=createResponse(Status::CODE_200,charConvert.to_bytes(outputData));
            response->putHeader("Content-Type","text/html; charset=utf-8");
            
            return response;
        }
        ENDPOINT("GET","/fileDownload",fileDownload,QUERY(String,path))
        {
            OATPP_LOGD("Download","Path=%s",path->c_str());

            std::stringstream streamFile;
            std::ifstream openFile(path->c_str(),std::ios::binary);
            streamFile<<openFile.rdbuf();
            auto file=streamFile.str();
            //OATPP_LOGD("Download","Transfer Data Size = %d",file->size());
            auto response=createResponse(Status::CODE_200,file);
            response->putHeader(Header::CONTENT_TYPE, "application/octet-stream");
            std::string fileName=path->substr(path->find_last_of('/')+1,path->length() - path->find_last_of('/')-1);
            response->putHeader("Content-disposition",fmt::format("attachment;filename={}",fileName));
            return response;
        }
        ENDPOINT("POST","/fileUpload",upload,REQUEST(std::shared_ptr<IncomingRequest>,request))
        {
            String currentPath=request->getHeader("Upload-Path");
            std::string decodeURL=currentPath->c_str();
            decodeURL=base64_decode(decodeURL);
            decodeURL=URLDecode(decodeURL);
            OATPP_LOGD("Upload","Upload File Path=%s",decodeURL.c_str());
            try
            {
                oatpp::data::stream::FileOutputStream fileOutputStream(decodeURL.c_str());
                request->transferBodyToStream(&fileOutputStream);
            }
            catch(const std::exception& e)
            {
                OATPP_LOGE("UploadFile","Output ERROR: %s",e.what());
                return createResponse(Status::CODE_500,"Can't Upload File");
            }
            return createResponse(Status::CODE_200,"File Upload Success");
        }
        ENDPOINT("POST","/fileDelete",FileDelete,REQUEST(std::shared_ptr<IncomingRequest>,request))
        {
            std::string path=request->readBodyToString();
            if(path.length()>100)
            {
                OATPP_LOGE("FileDelete","File Path too long");
                return createResponse(Status::CODE_500,"File Path too long");
            }
            OATPP_LOGI("FileDelete","Delete file Path=%s",path.c_str());
            if(std::filesystem::remove(std::filesystem::path(path.c_str())))
            {
                OATPP_LOGI("FileDelete","File is Deleted, Path=%s",path.c_str());
                return createResponse(Status::CODE_200);
            }
            else
            {
                OATPP_LOGE("FileDelete","Can't Delete File, Path=%s",path.c_str());
                return createResponse(Status::CODE_500);
            }
        }
        ENDPOINT("POST","/fileRename",FileRename,BODY_DTO(Object<RenameDTO>,renameDTO))
        {
            try
            {
                OATPP_LOGI("FileRename","File is Rename, Path=%s, To=%s",renameDTO->Path->c_str(),renameDTO->NewName->c_str());
                std::filesystem::rename(renameDTO->Path->c_str(),renameDTO->NewName->c_str());
            }
            catch(const std::exception& e)
            {
                return createResponse(Status::CODE_500,"Can't Rename File");
            }
            return createResponse(Status::CODE_200);
        }
};

#include OATPP_CODEGEN_BEGIN(ApiController)

#endif